using System.Text;

namespace System;
/// <summary>
/// 
/// </summary>
public class RandomUtils
{
    #region const fields
    /// <summary>
    /// 大写A-Z
    /// </summary>
    private const string UpperLetter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    /// <summary>
    /// 小写a-z
    /// </summary>
    private const string LowerLetter = "abcdefghijklmnopqrstuvwxyz";
    /// <summary>
    /// 纯数字
    /// </summary>
    private const string Number = "0123456789";
    #endregion const fields
    /// <summary>
    /// global的随机因子
    /// </summary>
    private static readonly Random _global = new Random();
    /// <summary>
    /// 线程安全的Random
    /// </summary>
    [ThreadStatic]
    private static Random _local = new Random();

    /// <summary>
    /// 线程安全的Random
    /// </summary>
    public static Random ThreadSafeRandom
    {
        get
        {
            if (_local is not null)
            {
                return _local;
            }

            lock (_global)
            {
                if (_local is not null)
                {
                    return _local;
                }

                int seed = _global.Next();
                _local = new Random(seed);

                return _local;
            }
        }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static int Next()
        => ThreadSafeRandom.Next();

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static int Next(int maxValue)
        => ThreadSafeRandom.Next(maxValue);

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static int Next(int minValue, int maxValue)
        => ThreadSafeRandom.Next(minValue, maxValue);

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static double NextDouble()
        => ThreadSafeRandom.NextDouble();

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static void NextBytes(byte[] buffer)
        => ThreadSafeRandom.NextBytes(buffer);
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static string RandomString(
        int length = 6,
        bool letters = true,
        bool numbers = true,
        bool withLower = true)
    {
        if (!letters && !numbers)
            throw new ArgumentException("MustHaveNumberOrLetters");

        var builder = new StringBuilder();

        if (letters)
        {
            builder.Append(UpperLetter);

            if (withLower)
            {
                builder.Append(LowerLetter);
            }
        }

        if (numbers)
        {
            builder.Append(Number);
        }

        var chars = builder.ToString();

        var elements = Enumerable.Repeat(chars, length);

        var generated = elements.Select(s => s[ThreadSafeRandom.Next(s.Length)]).ToArray();

        return new string(generated);
    }
}